﻿using Newtonsoft.Json;
using WH.Model.OrgContext;
using WH.Model.Systems;
using WH.Repositories.BaseRepositories;
using WH.Repositories.IRepositories.ISystem;
using WH.Common.Cache;
using WH.Common.Constant;
using SqlSugar;
using System.Linq.Expressions;

namespace WH.Repositories.Repositories.System
{
    public class KeyValueRepository : BaseRepository<KeyValueEntity>, IKeyValueRepository
    {
        private readonly ICaching _caching;

        public KeyValueRepository(ISqlSugarClient dbContext, OrganizationContext organizationContext, ICaching caching) : base(dbContext, organizationContext)
        {
            _caching = caching;
        }


        public async Task<KeyValueEntity?> GetKeyValueByCodeAsync(string code)
        {
            var existKey = _caching.ContainsKey<string>(BusinessFunction.KeyValueCacheKey);

            KeyValueEntity? data;

            if (existKey)
            {
                var cacheValue = await _caching.HGetAllAsync<KeyValueEntity>(BusinessFunction.KeyValueCacheKey);

                cacheValue.TryGetValue(code, out data);
            }
            else
            {
                var keyvals = await FindAllAsync(x => x.IsEnable);


                IDictionary<string, string> dics = new Dictionary<string, string>();

                foreach (var item in keyvals)
                {
                    dics.Add(item.Code, JsonConvert.SerializeObject(item));
                }

                data = keyvals.FirstOrDefault(x => x.Code == code);

                await _caching.HMSetAsync(BusinessFunction.KeyValueCacheKey, dics);
            }

            return data;
        }

        public override async Task<int> RemoveAsync(Expression<Func<KeyValueEntity, bool>> predicate)
        {
            var data = await FirstOrDefaultAsync(predicate);

            var ids = new List<string>();

            if (data is not null)
            {
                ids.Add(data.Id);

                var childIds = await GetChildIds(data.Id);

                ids.AddRange(childIds);
            }

            return await base.RemoveAsync(x => ids.Contains(x.Id));
        }

        public async Task<string[]> GetChildIds(string parentId)
        {
            var arr = new List<string>();
            var list = await FindAllAsync(x => x.ParentId == parentId && x.IsDeletable);
            arr.AddRange(list.Select(x => x.Id));

            foreach (var item in list)
            {
                var childIds = await GetChildIds(item.Id);
                arr.AddRange(childIds);
            }

            return arr.ToArray();
        }
    }
}
